package class8;

class test4
{
    private int a;
    private String b;

    public int c;
    public String d;

}
class test5 extends test4//将extend理解为C++公有继承，protected在子类中可以访问，在类外不能访问
{
    public void print()
    {
        //System.out.println(a);//
        //System.out.println(b);//错误，私有成员变量不能被子类访问
        System.out.println(c);//
        System.out.println(d);//正确，公有成员变量可以被子类访问
    }
}
//Java 有 4 种权限修饰符，访问范围从窄→宽依次为：private < 缺省（包访问权限） < protected < public。
//修饰符	本类内部	同一个包下的其他类	任意包下的子类	任意包下的任意类	核心场景
//private	√	    ×	             ×	         ×	        隐藏类的内部细节（如私有属性）
//缺省   	√	    √	             ×	         ×	        包内组件间协作（包外隐藏）
//protected	√	    √	             √	         ×	        父类向子类暴露可继承的成员
//public	√	    √	             √	         √	        对外提供公共接口（广泛访问）

//值得注意的是同一个包下缺省和protected都可以被访问!!!
class test6
{
    private void print1()
    {
        System.out.println("私有方法");
    }

    void print2()
    {
        System.out.println("缺省方法");
    }

    protected void print3()
    {
        System.out.println("受保护方法");
    }

    public void print4()
    {
        System.out.println("公有方法");
    }
}
class test7
{
    public void test()
    {
        test6 t=new test6();
        //t.print1();//
        t.print2();//
        t.print3();//
        t.print4();//
    }
}

//在java中不支持多继承，支持单继承，但是可以多层继承
class A//没有继承任何类，默认继承Object类
{
    public A()
    {
        super();
        System.out.println("A的构造函数");
    }

    public A(int x)
    {
        //super();//如果后面还要调用其他构造函数，这里不能调用super()，否则其他构造函数也会调用super()，super()只能调用一次
        //this()与super()不能重复出现，this也必须放在第一行
        this();//调用自己的无参构造函数,java中可以在构造函数中调用自己的其他构造函数
        System.out.println("A的有参构造函数");
    }

    public void print()
    {
        System.out.println("A");
    }

    public static void staticPrint()
    {
        System.out.println("A static");
    }

    int a=2025;
}
class B extends A
{
    public B()//子类的构造函数默认会调用父类的无参构造函数
    {
        //构造B的时候需要先构造A，这与C++一样

        //为什么子类构造器要调用父类构造器？
        //因为子类继承了父类的成员变量和成员函数，子类对象中包含了父类对象的部分
        //所以在创建子类对象时，必须先创建父类对象，才能保证子类对象的完整性
        //如果父类没有无参构造函数，则子类必须显式调用父类的有参构造函数

        //super();//也可以显式调用父类的构造函数，必须放在子类构造函数的第一行
        super(100);//显式调用父类的有参构造函数,必须放在子类构造函数的第一行
        System.out.println("B的构造函数");
    }

    //覆盖父类的方法,重写print方法
    @Override //可以验证是否正确覆盖了父类的方法
    //子类重写父类的方法时，访问权限要大于等于父类的方法
    //重写的方法的返回值类型要与父类的方法的返回值类型相同，或者范围更小
    //私有或者静态方法不能被重写
    public void print()
    {
        System.out.println("B");
    }

    public String toString()//对继承自Object类的toString()方法进行重写
    {
        return "This is class B";
    }

    public static void staticPrint()//隐藏父类的静态方法
    {
        System.out.println("B static");
    }

    int a=2026;//与父类的成员变量同名，隐藏了父类的成员变量
    //java中支持成员变量的隐藏，但是C++中不支持
    public void show()
    {
        int a=2027;//与成员变量同名，隐藏了成员变量，其实是就近原则
        System.out.println(a);//2027，访问的是局部变量
        System.out.println(this.a);//2026，访问的是子类的成员变量
        System.out.println(super.a);//2025，访问的是父类的成员变量
        //super可以理解为父类的当前对象
    }
}
class C extends B{}
//class D extends A,B{}//错误，java不支持多继承

public class oop_2 {
    public static void main(String[] args) {
        test5 t=new test5();
        t.print();
        System.out.println(t.c);//
        System.out.println(t.d);//正确，公有成员变量可以被类外访问
        //System.out.println(t.a);
        //System.out.println(t.b);//错误，私有成员变量不能被类外访问

        test7 t7=new test7();
        t7.test();

        A a=new A();
        a.print();//A
        B b=new B();
        b.print();//B
        System.out.println(b);//对象b的toString()方法被调用了
        b.staticPrint();

    }
}
